home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / misc / mdcfs.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  23KB  |  811 lines

  1. /*
  2.  * MDCFS: Minimal Dos Compatible File System
  3.  *
  4.  *   These routines provide the bare minimum needed to read and write
  5.  * files on an MS-DOS format floppy disk. You could use them with a hard
  6.  * disk as well, however since only 12 bit FAT's are supported, you are
  7.  * limited to a total of 4096 clusters, and total drive space is limited
  8.  * to 32MB due to 16 bit sector numbers (assuming 512 byte sectors).
  9.  *
  10.  *   The functions were written for use in embedded systems (where memory
  11.  * is often limited), and therefore provide only the basic open, read/write,
  12.  * close and delete operations. I have documented the functions which
  13.  * manipulate the directory and FAT, and it should be fairly easy to add
  14.  * other features if you need them (directory display etc.). Only access to
  15.  * files in the ROOT directory is provided, subdirectories are NOT supported.
  16.  *
  17.  *   For simplicity and memory conservation, these functions buffer only 1
  18.  * sector (512 bytes) in memory. This makes them run quite slowly, but is
  19.  * adaquate for reading/writing setup information and occational data logging.
  20.  * If you have lots of memory and need extra speed, you could modify the
  21.  * functions to read/write multiple sectors (a cluster would be easy).
  22.  * You can also experiment with different interleave factors, to obtain
  23.  * optimim performance with the existing I/O functions.
  24.  *
  25.  *   As they stand, the functions really support access to only one drive
  26.  * at a time. You can use multiple drives if you call "open_drive()" between
  27.  * disk operations to the separate drives. This "switches" the active drive
  28.  * to the specified one. Note however, that the selected drive will seek to
  29.  * track zero each time this function is called, so performing many small
  30.  * operations on more than one drive gets VERY inefficent. DO NOT read or
  31.  * write to an open file located on any drive other than the currently
  32.  * selected one! Call "open_drive()" first!
  33.  *
  34.  *   Concurrent access to multiple files (on the same drive) is supported,
  35.  * however since only one "work" buffer is used for directory/FAT access,
  36.  * the drive may have to perform extra read/write operation when switching
  37.  * from one file to the other. For this reason, it is best to try and do
  38.  * as many reads or writes as possible on one file before accessing others.
  39.  * Avoid many small operations to multiple files.
  40.  *
  41.  *   At present, only the first copy of the disk File Allocation Table
  42.  * (FAT) is used by these functions.
  43.  *
  44.  *   Functions read/write data in RAW (binary) form, without regard for
  45.  * NEWLINE characters etc. If you want to read/write ASCII text, you will
  46.  * have to write "wrapper" functions to drop RETURN (0x0D) characters on
  47.  * reading, and to add them before NEWLINE (0x0A) when writing.
  48.  *
  49.  *   Due to the use of 'C' structures, Version 3.0 (or later) of MICRO-C
  50.  * is REQUIRED! It should not be difficult to compile with a different
  51.  * compiler, but I have not attempted to do so.
  52.  *
  53.  * Copyright 1993-1994 Dave Dunfield
  54.  * All rights reserved.
  55.  *
  56.  * Permission granted for personal (non-commercial) use only.
  57.  */
  58.  
  59.  
  60. /* Required definitions from MICRO-C stdio.h (not part of MDCFS) */
  61. extern register printf();
  62. #define    FILE    unsigned
  63.  
  64.  
  65. /* Misc fixed parameters */
  66. #define    SECTOR_SIZE    512        /* Size of a disk sector */
  67. #define    BPB_SIZE    17        /* Number of bytes in BIOS Parm Block */
  68. #define    EMPTY        0xE5    /* Signals empty directory */
  69. #define    EOF            -1        /* End of file indicator */
  70. #define    ERROR        -2        /* Report error in file */
  71. #define    READ        0        /* File opened for READ */
  72. #define    WRITE        1        /* File opened for WRITE */
  73.  
  74.  
  75. /*
  76.  * Structure of MSDOS directory entry
  77.  */
  78. struct Dentry {
  79.     unsigned char    Dname[11];        /* Filename + extension */
  80.     unsigned char    Dattr;            /* File attributes */
  81.     unsigned char    Dreserved[10];    /* Reserved area */
  82.     unsigned        Dtime;            /* Time last modified */
  83.     unsigned        Ddata;            /* Date last modified */
  84.     unsigned        Dcluster;        /* First cluster number */
  85.     unsigned        Dsizel;            /* File size (LOW) */
  86.     unsigned        Dsizeh; } ;        /* File size (HIGH) */
  87.  
  88. /*
  89.  * Structure of internal file control block
  90.  */
  91. struct Fblock {
  92.     unsigned char     Fattr;            /* Open attributes */
  93.     unsigned char     Fsector;        /* Sector within cluster */
  94.     struct Dentry    *Fdirptr;        /* Pointer to directory entry */
  95.     unsigned        Fdirsec;        /* Directory sector */
  96.     unsigned        Ffirstcls;        /* First cluster in file */
  97.     unsigned        Flastcls;        /* Last cluster read/written */
  98.     unsigned        Fnextcls;        /* Next cluster to read/write */
  99.     unsigned        Foffset;        /* Read/Write offset */
  100.     unsigned        Fsizel;            /* File size (LOW) */
  101.     unsigned        Fsizeh;            /* File size (HIGH) */
  102.     unsigned char    Fbuffer[]; } ;    /* Data transfer buffer */
  103.  
  104.  
  105. /* Internal "work" sector variables */
  106. unsigned    wrkdrv = 0,                /* Current work drive number */
  107.              wrksec = -1;            /* Current work sector number */
  108. char        wrkchg = 0;                /* Indicates work sector changed */
  109. unsigned char wrkbuff[SECTOR_SIZE];    /* Work sector buffer */
  110.  
  111. /* Active drive information (other than contained in BPB) */
  112. char        active_drive = -1;        /* Open disk drive number */
  113. unsigned    dirsec = 5,                /* First sector of directory */
  114.             datasec = 12;            /* First sector of data area */
  115.  
  116. /* Disk information (from BIOS Parameter Block) */
  117. unsigned int    bytsec    = 512;        /* Bytes / sector */
  118. unsigned char    seccls    = 2;        /* Sectors / cluster */
  119. unsigned int    ressec    = 1;        /* # reserved sectors */
  120. unsigned char    numfat    = 2;        /* Number of FAT's */
  121. unsigned int    dirent    = 112;        /* Number of directory entries */
  122. unsigned int    sectors    = 720;        /* Sectors on disk */
  123. unsigned char    mediaid    = 0xFD;        /* Media ID byte */
  124. unsigned int    secfat    = 2;        /* Sectors / fat */
  125. unsigned int    sectrk    = 9;        /* Sectors / track */
  126. unsigned int    numhead    = 2;        /* Number of heads */
  127.  
  128.  
  129. /*
  130.  * Function Prototypes
  131.  */
  132. extern struct Dentry *lookup(), *create_file();
  133.  
  134.  
  135. /*
  136.  * File accessing functions:
  137.  *
  138.  *    open_drive(drive)            - Initialize a drive for file access
  139.  *        drive    - Drive id (0=A, 1=B ...)
  140.  *
  141.  *    open_file(name, attrs)        - Open file for read or write
  142.  *        name    - Name of file to open
  143.  *        attrs    - Open attributes: READ or WRITE
  144.  *        returns : Pointer to file structure, or 0 if failure
  145.  *
  146.  *    close_file(fp)                - Close an open file
  147.  *        fp        - Pointer to open file structure
  148.  *
  149.  *    read_byte(fp)                - Read a byte from an open file
  150.  *        fp        - Pointer to open file structure
  151.  *        returns : Value read (0-255), -1 if EOF, -2 if not open for read
  152.  *
  153.  *    write_byte(byte, fp)        - Write a byte to a file
  154.  *        byte    - Value to write to file (0-255)
  155.  *        returns : Value written (0-255) or -2 if error
  156.  *
  157.  *    delete_file(name)            - Erases the named file
  158.  *        name    - Name of file to erase
  159.  *        returns : 0 if Success, -1 if failure (file not found)
  160.  */
  161.  
  162. /*
  163.  * Open a disk drive and set up control information
  164.  *
  165.  * THIS FUNCTION MUST BE CALLED BEFORE ACCESSING ANY FILES,
  166.  * AND ANYTIME YOU SWITCH TO ACCESS A DIFFERENT DRIVE.
  167.  */
  168. open_drive(drive)
  169.     char drive;
  170. {
  171.     read_work(active_drive = drive, 0);
  172.     memcpy(&bytsec, wrkbuff+11, BPB_SIZE);
  173.     dirsec    = (numfat * secfat) + ressec;
  174.     datasec    = ((((dirent * sizeof(struct Dentry)) + bytsec) - 1) / bytsec) + dirsec;
  175. }
  176.  
  177. /*
  178.  * Open a file & return a pointer to an allocated file structure
  179.  */
  180. struct Fblock *open_file(name, attrs)
  181.     char *name;
  182.     int attrs;
  183. {
  184.     struct Dentry *dirptr;
  185.     struct Fblock *fp;
  186.  
  187.     if(dirptr = lookup(name)) {                    /* File already exists */
  188.         if(attrs == WRITE)                        /* Zero size on write */
  189.             dirptr->Dsizel = dirptr->Dsizeh = 0; }
  190.     else {
  191.         if(attrs != WRITE)                        /* Not writing file */
  192.             return 0;
  193.         if(!(dirptr = create_file(name, 0)))    /* Unable to create */
  194.             return 0; }
  195.  
  196.     /* Allocate buffer for file control block */
  197.     if(!(fp = malloc(bytsec+sizeof(struct Fblock))))
  198.         return 0;
  199.  
  200.     /* Fill in file control block from directory information */
  201.     fp->Fdirsec        = wrksec;
  202.     fp->Fdirptr        = dirptr;
  203.     fp->Fattr        = attrs;
  204.     fp->Fnextcls    = fp->Ffirstcls = dirptr->Dcluster;
  205.     fp->Fsizel        = dirptr->Dsizel;
  206.     fp->Fsizeh        = dirptr->Dsizeh;
  207.     fp->Fsector        = fp->Foffset = fp->Flastcls = 0;
  208.  
  209.     return fp;
  210.  
  211. }
  212.  
  213. /*
  214.  * Close an open file
  215.  */
  216. c